from django.conf import settings
from django_redis import get_redis_connection
from rest_framework import serializers
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
from rest_framework_jwt.settings import api_settings

from oauth.models import OauthQQUser
from users.models import User


class QQAuthUserSerializer(serializers.ModelSerializer):
    token = serializers.CharField(read_only=True, label="操作凭证")
    openid = serializers.CharField(write_only=True, label="openid")
    sms_code = serializers.CharField(max_length=6, min_length=6, write_only=True, label="短信验证码")
    mobile = serializers.RegexField(regex=r'^1[3-9]\d{9}$', label='手机号')  # 继承模型的序列化器中mobile字段唯一值取消需要重写mobile字段
    user_id = serializers.IntegerField(read_only=True)

    class Meta:
        model = User
        fields = ['mobile', 'password', 'sms_code', 'openid', 'username', 'token', 'user_id', 'id']
        extra_kwargs = {
            'password': {
                'write_only': True,
                'max_length': 20,
                'min_length': 8,
                'error_messages': {
                    'max_length': '密码过长',
                    'min_length': '密码过短'
                }
            },
            'username': {
                'read_only': True,
                'max_length': 20,
                'min_length': 5,
                'error_messages': {
                    'max_length': '名字过长',
                    'min_length': '名字过短'
                }
            },
        }

    def validate(self, attrs):
        # 验证openid
        tjs = TJS(settings.SECRET_KEY)
        # 解密
        try:
            data = tjs.loads(attrs["openid"])
        except:
            raise serializers.ValidationError("openid错误")
        openid = data.get("openid")

        # f添加openid到attrs中
        attrs["openid"] = openid

        # 验证短信验证码
        # 连接redis取出验证码
        conn = get_redis_connection("verify_codes")
        real_sms = conn.get("sms_{}".format(attrs["mobile"]))

        # 判断是否能取出验证码
        if not real_sms:
            raise serializers.ValidationError("验证码已失效")
        # 比对验证码
        if real_sms.decode() != attrs["sms_code"]:
            raise serializers.ValidationError("验证码不匹配")

        # 验证用户是否注册过
        try:
            user = User.objects.get(mobile=attrs["mobile"])
        # 没注册
        except:
            return attrs
        else:
            # 已经注册
            # 密码校验
            if not user.check_password(attrs["password"]):
                raise serializers.ValidationError("密码不匹配")
            attrs["user"] = user
            return attrs

    def create(self, validated_data):
        """因为不需要所有字段都进行保存，所以重写create方法"""
        user = validated_data.get("user", None)
        # 判断用户是否注册
        if user is None:
            #  create_user方法会对password进行加密
            user = User.objects.create_user(username=validated_data['mobile'], password=validated_data['password'],
                                            mobile=validated_data['mobile'])
        OauthQQUser.objects.create(user=user, openid=validated_data['openid'])
        # 生成token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        # 用户对象额外添加token属性
        user.token = token
        user.user_id = user.id

        return user
